namespace Xmef.Engine.Internal
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using Xmef.Engine;
    using Xmef.Interfaces;
    using Xmef.Library;

    [Serializable]
    internal class PluginObject<T> : PluginServiceProvider<IPluginObject>, IPluginObjectInternal, IPluginObject<T>, IPluginObjectActivator<T>, IPluginObjectActivator, IPluginObject, IPluginServiceProvider<IPluginObject>, IPluginService, IPluginServiceProvider<IPluginService>, IPluginIdentity
    {
        private readonly IPluginObjectActivatorInternal _activator;
        private bool _active;
        private readonly IPluginAssemblyInternal _assembly;
        private readonly IPluginAttributes _attributes;
        private Type _interface;
        private readonly Type _type;

        public PluginObject(Type type, IPluginContextInternal context)
        {
            this._interface = typeof(T);
            this._type = type;
            this._assembly = context.Assembly;
            this._activator = new PluginObjectActivator<T>(type, context, this._assembly.Activator);
            this._attributes = new PluginAttributes(type, this._assembly.GetAttributes(this._type));
        }

        public PluginObject(Type type, T obj)
        {
        }

        public bool Activate()
        {
            if (!this._active)
            {
                this._active = true;
                return true;
            }
            return false;
        }

        public bool Deactivate()
        {
            if (this._active)
            {
                this._active = false;
                return true;
            }
            return false;
        }

        public bool IsPluginType(Type type)
        {
            return (this._type == type);
        }

        public bool IsSubtype(Type type)
        {
            return TypeHelper.IsSubtype(type, typeof(T));
        }

        public void ProcessObject(Action<T> action)
        {
            IPluginObjectActivator<T> activator = this._activator as IPluginObjectActivator<T>;
            if (activator != null)
            {
                activator.ProcessObject(action);
            }
        }

        public bool ProcessObject(Predicate<T> match)
        {
            IPluginObjectActivator<T> activator = this._activator as IPluginObjectActivator<T>;
            return ((activator != null) && activator.ProcessObject(match));
        }

        public void ProcessService(Action<Type> action)
        {
            this._activator.ProcessService(action);
        }

        public bool ProcessService(Predicate<Type> match)
        {
            return this._activator.ProcessService(match);
        }

        public override string ToString()
        {
            return string.Format(CultureInfo.InvariantCulture, "{0}:{1}", new object[] { this._type.Name, GetType().Name });
        }

        int IPluginService.Count(Type type)
        {
            return PluginService.Count(type);
        }

        IGenericCollection<IPluginObject> IPluginService.GetObjects(Type type)
        {
            return PluginService.GetObjects(type);
        }

        public IPluginAttributes Attributes
        {
            get
            {
                return this._attributes;
            }
        }

        public IPluginHost Host
        {
            get
            {
                if (this._activator != null)
                {
                    return this._activator.InternalContext.Host;
                }
                return null;
            }
        }

        public Type InterfaceType
        {
            get
            {
                return this._interface;
            }
        }

        public IPluginObjectActivatorInternal InternalActivator
        {
            get
            {
                return this._activator;
            }
        }

        public bool IsActive
        {
            get
            {
                return this._active;
            }
        }

        public Type ObjectType
        {
            get
            {
                return this._type;
            }
        }

        Type IPluginService.ServiceType
        {
            get
            {
                return PluginService.ServiceType;
            }
        }
    }
}

